/*
 * timer.cpp
 */

#include "timer.h"
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <strings.h>
#include <inttypes.h>
#include <pthread.h>
#include <math.h>
#include "execStruct.h"


Timer::Timer() {
	ltime = time(NULL);
	Tm = localtime(&ltime);
	gettimeofday(&detail_time,NULL);
	hourIni = Tm->tm_hour;
	minuteIni = Tm->tm_min;
	secondIni = Tm->tm_sec;
	usIni = detail_time.tv_usec;
}

Timer::~Timer() {

}

void Timer::addListenerOneHz(oneHzListener *listener){
	listenersOneHz.push_back(listener);
}

void Timer::addListenerFiveHz(fiveHzListener *listener){
	listenersFiveHz.push_back(listener);
}

void Timer::addListenerFiftyHz(fiftyHzListener *listener){
	listenersFiftyHz.push_back(listener);
}

void Timer::removeListenerOneHz(oneHzListener *listener){
	listenersOneHz.remove(listener);
}

void Timer::removeListenerFiveHz(fiveHzListener *listener){
	listenersFiveHz.remove(listener);
}

void Timer::removeListenerFiftyHz(fiftyHzListener *listener){
	listenersFiftyHz.remove(listener);
}

void Timer::startTiming(){
	pthread_t threadFiftyHz;
	pthread_t threadFiveHz;
	pthread_t threadOneHz;
	int rf = pthread_create(&threadFiftyHz, NULL, &Timer::startFiftyHzThread, this);
	int ra = pthread_create(&threadFiveHz, NULL, &Timer::startFiveHzThread, this);
	int ro = pthread_create(&threadOneHz, NULL, &Timer::startOneHzThread, this);
    if (rf || ro || ra){
        printf("ERROR generating timing threads in timer.cpp");
        exit(-1);
     }
}

void *Timer::startFiftyHzThread(void *ptr){
	Timer *Timerptr = (Timer *)ptr;
	Timerptr->startFiftyHzLoop();
	pthread_exit(NULL);
}

void *Timer::startFiveHzThread(void *ptr){
	Timer *Timerptr = (Timer *)ptr;
	Timerptr->startFiveHzLoop();
	pthread_exit(NULL);
}

void *Timer::startOneHzThread(void *ptr){
	Timer *Timerptr = (Timer *)ptr;
	Timerptr->startOneHzLoop();
	pthread_exit(NULL);
}

void Timer::startOneHzLoop(){
	while (!pv.killMariner) {
		usleep(999500);
		notifyListenersOneHz();
	}
}

void Timer::startFiveHzLoop(){
	while (!pv.killMariner) {
		usleep(199800);
		notifyListenersFiveHz();
	}
}

void Timer::startFiftyHzLoop(){
	while (!pv.killMariner) {
		usleep(19500);
		notifyListenersFiftyHz();
	}
}

void Timer::notifyListenersFiftyHz(){
	list<fiftyHzListener*>::iterator it;
	for(it = listenersFiftyHz.begin(); it != listenersFiftyHz.end(); ++it){
		(*it)->fiftyHzUpdate(*this);
	}
}

void Timer::notifyListenersOneHz(){
	list<oneHzListener*>::iterator it;
	for(it = listenersOneHz.begin(); it != listenersOneHz.end(); ++it){
		(*it)->oneHzUpdate(*this);
	}
}

void Timer::notifyListenersFiveHz(){
	list<fiveHzListener*>::iterator it;
	for(it = listenersFiveHz.begin(); it != listenersFiveHz.end(); ++it){
		(*it)->fiveHzUpdate(*this);
	}
}

void Timer::stopTiming(){
	pv.killMariner = true;
}

double Timer::getTime() {
	ltime = time(NULL);
	Tm = localtime(&ltime);
	gettimeofday(&detail_time,NULL);

	double h = Tm->tm_hour - hourIni;
	double m = Tm->tm_min - minuteIni;
	double s = Tm->tm_sec - secondIni;
	double us = detail_time.tv_usec - usIni;

	double t = 3600*h + 60*m + s + 0.000001*us;
	return t;
}
